// ResultViewModel.kt
package com.example.nutritionmanager.viewModels

import android.annotation.SuppressLint
import android.content.Context
import android.net.Uri
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.nutritionmanager.api.NutritionService
import com.example.nutritionmanager.api.RecordService
import com.example.nutritionmanager.api.ResultService
import com.example.nutritionmanager.bodys.requestBodys.Record
import com.example.nutritionmanager.bodys.requestBodys.RecordItem
import com.example.nutritionmanager.bodys.responseBodys.Nutrition
import com.example.nutritionmanager.bodys.responseBodys.OCRResult
import com.example.nutritionmanager.bodys.responseBodys.OCRResultItem
import com.example.nutritionmanager.event.EventBus
import com.example.nutritionmanager.event.IntakeRefreshEvent
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import javax.inject.Inject
import kotlin.collections.plus
import kotlin.text.isNullOrBlank
import kotlin.text.toDouble
import kotlin.text.toDoubleOrNull

sealed class ResultState {
    object Idle : ResultState() // 初始状态
    object Loading : ResultState() // 加载中
    data class Success(val ocrResult: OCRResult) : ResultState() // 成功获取OCR结果
    data class Error(val error: String) : ResultState() // 获取OCR结果时发生错误
    data class SaveSuccess(val message: String) : ResultState() // 保存成功
    data class SaveError(val error: String) : ResultState() // 保存时发生错误
}

@HiltViewModel
class ResultViewModel @Inject constructor(
    private val resultService: ResultService,
    private val recordService: RecordService
) : ViewModel() {

    private val _resultState = MutableStateFlow<ResultState>(ResultState.Idle)
    val resultState = _resultState.asStateFlow()

    // 管理选中的OCR结果项
    private val _selectedResults = MutableStateFlow<List<OCRResultItem>>(emptyList())
    val selectedResults = _selectedResults.asStateFlow()

    // 管理selectedResults的输入值（amount）
    private val _selectedResultInputs = MutableStateFlow<Map<Int, String>>(emptyMap())
    val selectedResultInputs = _selectedResultInputs.asStateFlow()

    private val _foodWeight = MutableStateFlow(100)
    val foodWeight = _foodWeight.asStateFlow()

    // 管理食物重量
    private val _foodWeightInput = MutableStateFlow(foodWeight.value)
    val foodWeightInput = _foodWeightInput.asStateFlow()

    // 原始营养值（每100克）
    private val _originalNutritionValues = MutableStateFlow<List<OCRResultItem>>(emptyList())
    val originalNutritionValues = _originalNutritionValues.asStateFlow()

    /**
     * 获取OCR识别结果
     */
    fun fetchResult() {
        viewModelScope.launch {
            _resultState.value = ResultState.Loading
            try {
                val response = resultService.getResult()
                if (response.isSuccessful) {
                    val ocrResult = response.body()
                    if (ocrResult != null) {
                        _resultState.value = ResultState.Success(ocrResult)
                        ocrResult.results.forEach { item ->
                            _selectedResults.value = _selectedResults.value + item
                            // 初始化 selectedResultInputs，将每个营养成分的 amount 转换为字符串
                            val initialInputs = ocrResult.results.associate { it.nutritionId to it.amount.toString() }
                            _selectedResultInputs.value = initialInputs
                        }
                    } else {
                        _resultState.value = ResultState.Error("OCR结果为空")
                    }
                } else {
                    _resultState.value = ResultState.Error("获取OCR结果失败，错误代码：${response.code()}")
                }
            } catch (e: Exception) {
                _resultState.value = ResultState.Error("发生错误：${e.localizedMessage}")
            }
        }
    }

    fun prepareImageFilePart(file: File): MultipartBody.Part {
        val requestFile = file.asRequestBody("image/*".toMediaTypeOrNull())
        return MultipartBody.Part.createFormData("file", file.name, requestFile)
    }

    fun uriToFile(context: Context, uri: Uri): File {
        val inputStream = context.contentResolver.openInputStream(uri)
        val tempFile = File.createTempFile("upload", ".jpg", context.cacheDir)
        tempFile.outputStream().use { output ->
            inputStream?.copyTo(output)
        }
        return tempFile
    }


    fun uploadImage(context: Context, imageUri: Uri) {
        viewModelScope.launch {
            try {
                _resultState.value = ResultState.Loading

                // 1. 通过 Uri 转 File
                val file = uriToFile(context, imageUri)

                // 2. 转 Multipart
                val imagePart = prepareImageFilePart(file)

                // 3. 发请求
                val response = resultService.recognizeNutritionTable(imagePart)
//                val response = resultService.getResult()

                if (response.isSuccessful) {
                    val result = response.body()
                    if (result != null) {
                        _resultState.value = ResultState.Success(result)
                        _selectedResults.value = result.results
                        _originalNutritionValues.value = result.results
                        _foodWeight.value = result.weight
                        _foodWeightInput.value = result.weight
                        _selectedResultInputs.value = result.results.associate {
                            it.nutritionId to it.amount.toString()
                        }
                    } else {
                        _resultState.value = ResultState.Error("识别失败：空响应")
                    }
                } else {
                    _resultState.value = ResultState.Error("识别失败：${response.code()}")
                }
            } catch (e: Exception) {
                e.printStackTrace()
                _resultState.value = ResultState.Error("上传失败：${e.message}")
            }
        }
    }


    /**
     * 添加选中的OCR结果项
     */
    fun addSelectedResult(nutrition: Nutrition) {
        val ocrItem = OCRResultItem(nutrition.nutritionId, nutrition.nutritionName, nutrition.unit, 0.0, true, null)
        if (!_selectedResults.value.contains(ocrItem)) {
            _selectedResults.value = _selectedResults.value + ocrItem
        }
    }

    /**
     * 从选中的OCR结果项中移除
     */
    fun removeSelectedResult(ocrItem: OCRResultItem) {
        _selectedResults.value = _selectedResults.value - ocrItem
    }

    /**
     * 设置OCR识别结果（如果需要手动设置）
     *
     * @param result OCR识别结果
     */
    fun setOCRResult(result: OCRResult) {
        _resultState.value = ResultState.Success(result)
    }

    /**
     * 用于更新食用重量
     */
    @SuppressLint("DefaultLocale")
    fun updateFoodWeightInput(newWeight: String) {
        _foodWeightInput.value = newWeight.toInt()

        val weightDouble = newWeight.toDoubleOrNull() ?: return

        // 根据新重量按比例计算各个营养成分的新值
        val updatedInputs = _originalNutritionValues.value.associate { item ->
            val scaledAmount = item.amount * (weightDouble / foodWeight.value.toDouble())
            item.nutritionId to String.format("%.2f", scaledAmount)
        }
        _selectedResults.value = _originalNutritionValues.value.map { item ->
            val scaledAmount = item.amount * (weightDouble / foodWeight.value.toDouble())
            item.copy(amount = scaledAmount)
        }
        _selectedResultInputs.value = updatedInputs
    }

    /**
     * 用于更新每份重量
     */
    fun updateFoodWeight(newWeight: String) {
        _foodWeight.value = newWeight.toInt()
    }


    /**
     * 更新选中OCR结果项的amount
     */
    fun updateRecordAmount(nutritionId: Int, newAmount: String) {
        _selectedResultInputs.value += (nutritionId to newAmount)

    }

    /**
     * 重置当前状态到Idle
     */
    fun resetState() {
        _resultState.value = ResultState.Idle
        _selectedResults.value = emptyList()
    }

    // 保存营养记录的方法
    fun saveNutritionRecord(date: String, mealType: Int) {
        viewModelScope.launch {
            _resultState.value = ResultState.Loading
            try {
                // 1. 验证输入有效性
                val validationResult = validateInputs()
                if (!validationResult.isValid) {
                    _resultState.value = ResultState.SaveError(validationResult.errorMessage)
                    return@launch
                }
                // 2. 构建请求体
                val record = buildRecord(date, mealType)
                // 3. 调用API
                val response = recordService.addNutritionRecord(record)

                if (response.isSuccessful) {
                    _resultState.value = ResultState.SaveSuccess("记录保存成功")
                    EventBus.post(IntakeRefreshEvent.RefreshData)
                } else {
                    val errorBody = response.errorBody()?.string() ?: "未知错误"
                    _resultState.value = ResultState.SaveError("保存失败: $errorBody")
                }
            } catch (e: Exception) {
                _resultState.value = ResultState.SaveError("网络错误: ${e.localizedMessage}")
            }
        }
    }

    // 输入验证
    private fun validateInputs(): ValidationResult {
        val invalidItems = selectedResults.value.filter { nutrition ->
            val value = selectedResultInputs.value[nutrition.nutritionId]
            value.isNullOrBlank() || value.toDoubleOrNull() == null
        }

        return if (invalidItems.isNotEmpty()) {
            val names = invalidItems.joinToString { it.nutritionName }
            ValidationResult(false, "以下数值无效: $names")
        } else {
            ValidationResult(true)
        }
    }

    // 构建请求体
    private fun buildRecord(date: String, mealType: Int): com.example.nutritionmanager.bodys.requestBodys.Record {
        return Record(
            date = date,
            mealType = mealType,
            nutrients = selectedResults.value.map { nutrition ->
                RecordItem(
                    nutritionId = nutrition.nutritionId,
                    nutritionName = nutrition.nutritionName,
                    amount = selectedResultInputs.value[nutrition.nutritionId]?.toDouble() ?: 0.0
                )
            }
        )
    }

    // 验证结果数据类
    private data class ValidationResult(
        val isValid: Boolean,
        val errorMessage: String = ""
    )
}
